﻿using JSONDB.helpers;
using MongoDB.Bson;
using MongoDB.Driver;
using NLog;
using NPOI.SS.Formula.Functions;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using OPCService.Model;

namespace OPCService.Utils
{
    class MongoDbHelper
    {

        /// <summary>
        /// 发送集合：colname_send
        /// </summary>
        private IMongoDatabase database;
        private static string connection = ConfigHelper.ReadConfig("connection");
        private static string colname = ConfigHelper.ReadConfig("colname");
        public Logger logger;

        private IMongoDatabase adminDatabase;

        public MongoDbHelper(string databaseName = "")
        {
            if (databaseName == String.Empty)
            {
                databaseName = connection;
            }
            this.database = GetDb(databaseName);
            this.adminDatabase = database.Client.GetDatabase("admin");
        }

        public IMongoDatabase GetDb(string databaseName)
        {
            var db = new MongoClient(databaseName).GetDatabase(new MongoUrlBuilder(databaseName).DatabaseName);
            return db;
        }

        public IMongoCollection<T> GetCollection<T>(string collName)
        {
            return database.GetCollection<T>(collName);
        }

        public List<T> findAll<T>(string tableName)
        {
            List<T> list = new List<T>();
            try
            {
                var collection = GetCollection<T>(collName: tableName);
                FilterDefinition<T> filter = Builders<T>.Filter.Empty;
                list = collection.Find<T>(filter).ToList<T>();
            }
            catch (Exception ex)
            {
                logger.Error(ex);
            }
            return list;
        }

        public List<T> find<T>(string tableName, FilterDefinition<T> filter)
        {
            List<T> list = new List<T>();
            try
            {
                var collection = GetCollection<T>(collName: tableName);

                list = collection.Find<T>(filter).ToList<T>();
            }
            catch (Exception ex)
            {
                logger.Error(ex);
            }
            return list;
        }

        public List<T> findLimit<T>(string tableName, FilterDefinition<T> filter, SortDefinition<T> sort, int count)
        {
            List<T> list = new List<T>();
            try
            {
                var collection = GetCollection<T>(collName: tableName);

                list = collection.Find<T>(filter).Sort(sort).Limit(count).ToList<T>();
            }
            catch (Exception ex)
            {
                logger.Error(ex);
            }
            return list;
        }

        public List<T> findBySort<T>(string tableName, FilterDefinition<T> filter, SortDefinition<T> sort)
        {
            List<T> list = new List<T>();
            try
            {
                var collection = GetCollection<T>(collName: tableName);

                list = collection.Find<T>(filter).Sort(sort).ToList<T>();
            }
            catch (Exception ex)
            {
                logger.Error(ex);
            }
            return list;
        }

        public void deleteMany<T>(string tableName, FilterDefinition<T> filter)
        {
            try
            {
                var collection = GetCollection<T>(collName: tableName);

                collection.DeleteManyAsync(filter);
            }
            catch (Exception ex)
            {
                logger.Error(ex);
            }
        }

        public DbMessage Insert<T>(string collName, T document)
        {
            try
            {
                var coll = GetCollection<T>(collName);
                coll.InsertOne(document);
                return new DbMessage { Ex = string.Empty, iFlg = 1 };
            }
            catch (Exception ex)
            {
                logger.Error(ex);
                return new DbMessage { Ex = ex.Message, iFlg = -101 };
            }
        }

        public async Task<DbMessage> InsertMany<T>(string collName, List<T> documents)
        {
            try
            {
                var coll = GetCollection<T>(collName);
                coll.InsertMany(documents);
                return new DbMessage { Ex = string.Empty, iFlg = documents.Count };
            }
            catch (Exception ex)
            {
                logger.Error(ex);
                return new DbMessage { Ex = ex.Message, iFlg = -101 };
            }
        }
        
        public class DbMessage
        {
            public long iFlg { get; set; }
            public string Ex { get; set; }
        }
    }

}
